//
//  DealNetData.swift
//  Trans
//
//  Created by zcj on 2024/12/30.
//

import Foundation
import NetAction
class DealNetData:DealNetDataProtocol{
    
    func receiveData(id: ConId, data: Data) {
        //数据进行分割
        var index:Int = 0;
        var status:Bool = false
        while(true){
            let lenofph = PackageHead.headCount
            if(index+Int(lenofph) > data.count ){
                //                print("PackageHead.length is grater than data.count")
                //还有一些没有读完
                status = true
                break;
            }
            let phData = data.subdata(in: index..<index+Int(lenofph))
            let ph:PackageHead = PackageHead.decode(data: phData)!
            if(index+Int(ph.dataCount) > data.count ){
                //                print("PackageHead.dataCount is grater than data.count")
                //还有一些没有读完
                status = true
                break;
            }
            let msgData = data.subdata(in: index+Int(lenofph)..<index+Int(ph.dataCount))
            
            //处理
            //            callback(ph,msgData,false)
            dealData(id: id, ph: ph, data: msgData, status: false)
            
            index = index+Int(ph.dataCount)
            if(index > data.count){
                //刚好读完
                break
            }
        }
        if status {
            dealData(id: id, ph: PackageHead(), data: data.subdata(in: index..<data.count), status: true)
            
        }
        print("deal data all done")
    }
    
    func dealData(id:ConId,ph:PackageHead,data:Data,status:Bool){
        if status{//将剩余的数据添加进connection的lastdata里面
            if let cm = kzListener.conDic[id]{
                cm.lastData = data
            }
        }else{
            switch ph.type{
            case STRING_MESSAGE:do
                {
                    onreceiveStringMessage(id: id, data: data)
                    break
                }
            case FILE_MESSAGE_REQ:do
                {
                    onreceiveFileMsgReq(id: id, data: data)
                    break
                }
            case FILE_DATA:do
                {
                    onreceiveFileData(id: id, data: data)
                    break
                }
            case FILE_CANCEL:do
                {
                    onreceiveFileCancel(id: id, data: data)
                    break
                }
            case FILE_STOP:do
                {
                    onreceiveFileStop(id: id, data: data)
                    break
                }
            case FILE_RESUME:do
                {
                    onreceiveFileResume(id: id, data: data)
                    break
                }
            case RECONNECT:do
                {
                    onreceiveReconnect(id: id, data: data)
                    break
                }
            default:
                print("ph not have this type,type is \(ph.type)")
                
            }
        }
    }
    
    //处理文字信息的数据
    func onreceiveStringMessage(id:ConId,data:Data){
        if let strMsg:StringMessage = StringMessage.deCodeFromJson(jsonData: data){
            if let cm = kzListener.conDic[id]{
                cm.hostName = strMsg.hostName
                cm.wordsArr.append(strMsg)
                kzListener.conDic.state = true
            }
        }
    }
    
    //处理文件发送请求的数据
    func onreceiveFileMsgReq(id:ConId,data:Data){
        if let fileMsg:FileMessage = FileMessage.deCodeFromJson(jsonData: data){
            if let cm = kzListener.conDic[id]{
                cm.hostName = fileMsg.hostName
                let ftm = getFtmFromFm(fm: fileMsg)
                ftm.conID = id
                ftm.ip = getipFromEndpoint(addr: cm.con.endpoint.debugDescription)
                cm.fileDic[fileMsg.fileId] = ftm
                DispatchQueue.main.async{
                    kzListener.conDic.state = true
                }
                
                
                let fdm = FileDataMsg( filePath: ftm.absolutePath!)
                FileWriteManager.shared.addObjForKey(key: ftm.fileId, fdm: fdm)
            }
        }
    }
    
    func getFtmFromFm(fm:FileMessage) -> FileTransMessage{
        let ablolutePath:String = FileController.createDownloadFileName(userName: fm.hostName, fileName: fm.fileName)
        let ftm = FileTransMessage(fileName: fm.fileName, totalSize: fm.totalSize, downloadSize:0, state: DOWNLOADING, absolutePath: ablolutePath, startTime: Date().timeIntervalSince1970)
        ftm.fileId = fm.fileId
        return ftm
    }
    
    func onreceiveFileData(id:ConId,data:Data){
        if let fileData:FileData = FileData.deCodeFromJson(jsonData: data){
            if let cm = kzListener.conDic[id],let ftm  = cm.fileDic[fileData.fileId]{
                //将data写入文件
                FileWriteManager.shared.writeData(fileId: ftm.fileId, data: fileData.fileData)
                ftm.downloadSize += FSIZE(fileData.fileData.count)
                if ftm.downloadSize == ftm.totalSize!{
                    ftm.state = DOWNLOADCOMPLETE
                    FileWriteManager.shared.flushData(fileId: ftm.fileId)
                    FileWriteManager.shared.removeObjForKey(fileId:ftm.fileId)
                    cm.fileDic.removeValue(forKey:ftm.fileId)
                }else if( ftm.downloadSize > ftm.totalSize! ){
                    ftm.state = DOWNLOADFAILED
                    FileWriteManager.shared.flushData(fileId: ftm.fileId)
                    FileWriteManager.shared.removeObjForKey(fileId:ftm.fileId)
                    cm.fileDic.removeValue(forKey:ftm.fileId)
                    error_log("download failed : download size is bigger than totalsize")
                }
                info_log("onreceiveFileData done,data size is : \(fileData.fileData.count),downloadSize is: \(ftm.downloadSize),totalSize is \(ftm.totalSize ?? 0)")
            }
        }
    }
    
    func onreceiveFileCancel(id:ConId,data:Data){
        if let fileCancel:FileCancel = FileCancel.deCodeFromJson(jsonData: data){
            if let cm = kzListener.conDic[id]{
                cm.fileDic.removeValue(forKey: fileCancel.fileId)
                for index in fileDownloadArr.array.indices{
                    let ftm = fileDownloadArr.array[index]
                    if ftm.fileId == fileCancel.fileId{
                        ftm.state = DOWNLOADCANCEL
                        //删除本地文件
                        FileController.deleteFile(filePath: ftm.absolutePath!)
                        FileWriteManager.shared.removeObjForKey(fileId:ftm.fileId)
                        break
                    }
                }
            }
        }
    }
    
    func onreceiveFileStop(id:ConId,data:Data){
        if let fileStop:FileStop = FileStop.deCodeFromJson(jsonData: data),let cm = kzListener.conDic[id]{
            for index in fileDownloadArr.array.indices{
                let ftm = fileDownloadArr.array[index]
                if ftm.fileId == fileStop.fileId, ftm.state == DOWNLOADING{
                    ftm.state = DOWNLOADPAUSE
                    break
                }
            }
        }
    }
    
    func onreceiveFileResume(id:ConId,data:Data){
        if let fileResume:FileResume = FileResume.deCodeFromJson(jsonData: data),let cm = kzListener.conDic[id]{
            if fileResume.type == 1{
                for item in fileDownloadArr.array{
                    if item.fileId == fileResume.fileId && item.state == DOWNLOADPAUSE{
                        item.state = DOWNLOADING
                        item.startTime = Date().timeIntervalSince1970
                        let fdm = FileDataMsg( filePath: item.absolutePath!)
                        FileWriteManager.shared.addObjForKey(key: item.fileId, fdm: fdm)
                    }
                }
                return
            }
            
            for index in fileDownloadArr.array.indices{
                let ftm = fileDownloadArr.array[index]
                if ftm.fileId == fileResume.fileId,ftm.state == DOWNLOADPAUSE{
                    //判断文件是否存在，不存在就要发送相关提醒，同时删除相应的文件信息，存在获得改文件的大小作为 downloadSize
                    let resResume = FileResume(fileId: ftm.fileId,type: 1)
                   
                    if !FileManager.default.fileExists(atPath: ftm.absolutePath!){
                        resResume.msg = "接收方:\(ftm.fileName!)文件不存在,无法重新传输"
                            //设置ftm为downloadfailed
                        ftm.state = DOWNLOADFAILED
                    }else{
                        if let size = FileController.fileSize(filepath: ftm.absolutePath!){
                            resResume.size = size
                            ftm.downloadSize = size
                        }
                    }
                   
                    let pkgData = BaseData.pkgData(obj: resResume)
                    cm.con.send(content: pkgData, completion: .contentProcessed({ error in
                        if let err = error{
                            print(err)
                        }else{
                            if resResume.msg.isEmpty{
                                ftm.state = DOWNLOADING
                                let fdm = FileDataMsg( filePath: ftm.absolutePath!)
                                FileWriteManager.shared.addObjForKey(key: ftm.fileId, fdm: fdm)
                            }else{
                                ftm.state = DOWNLOADCANCEL
                                ftm.startTime = Date().timeIntervalSince1970
                            }
                        }
                    }))
                    break
                }
            }
        }
    }
    
    func onreceiveReconnect(id:ConId,data:Data){
        if let reconnect:ReConnect = ReConnect.deCodeFromJson(jsonData: data),let cm = kzListener.conDic[id]{
            guard  reconnect.reconnectType == 0 else{
                //client的回应报文：client接受到listen的请求重连之后，发送回应报文过来
                info_log("client->listen: reconnect with response . no need to response")
                if reconnect.side == 0{
                    let ip = getipFromEndpoint(addr: cm.con.endpoint.debugDescription)
                    fileDownloadArr.forEach { ftm in
                        if ftm.ip == ip{
                            cm.fileDic[ftm.fileId] = ftm
                            ftm.conID = id
                            let fdm = FileDataMsg(filePath: ftm.absolutePath!)
                            FileWriteManager.shared.addObjForKey(key: ftm.fileId, fdm: fdm)
                        }
                    }
                    //将未链接时的请求都执行了
                    ConContainerMsg.shared.performTask(ip: ip, side: .LISTENER, conid: id)
                }
                
                
                return
            }
            
            if reconnect.side == 0{//client的请求，直接回应
                info_log("client->listen: reconnect. then response reconnect to client")
                let rc = ReConnect(side: 1, type: 1)
                let pkgData = BaseData.pkgData(obj: rc)
                cm.con.send(content: pkgData, completion: .contentProcessed({ error in
                    if let error = error{
                        error_log("response to  reconnect failed: \(error.localizedDescription)")
                    }else{
                        //然后cm在filedownloadarr里面挑选对应的数据添加到cm.filedic里面
                        let ip = getipFromEndpoint(addr: cm.con.endpoint.debugDescription)
                        fileDownloadArr.forEach { ftm in
                            if ftm.ip == ip{
                                cm.fileDic[ftm.fileId] = ftm
                                ftm.conID = id
                                let fdm = FileDataMsg(filePath: ftm.absolutePath!)
                                FileWriteManager.shared.addObjForKey(key: ftm.fileId, fdm: fdm)
                            }
                        }
                        ConContainerMsg.shared.performTask(ip: ip, side: .LISTENER, conid: id)
                    }
                }))
                
                
            }else{//listen的请求，开启新的端口， 发送回应报文。
                //获得ip地址  //192.168.20.120:60421
                info_log("listen->client: reconnect. then new a client send -> listen")
                let ip = getipFromEndpoint(addr: cm.con.endpoint.debugDescription)
                let ipid = TCPClientManager.shared.sendReconnectMsg(ip: ip, side: 0, type: 1)
                if let client = TCPClientManager.shared.clientDic[ipid]{
                    fileUploadArr.forEach{ ftm in
                        if ftm.ip == ip{
                            client.fileDic[ftm.fileId] = ftm
                            ftm.conID = ipid
                            let fdm = FileDataMsg(filePath: ftm.absolutePath!)
                            FileWriteManager.shared.addObjForKey(key: ftm.fileId, fdm: fdm)
                        }
                    }
                    ConContainerMsg.shared.performTask(ip: ip, side: .CLIENT, conid: client.conId)
                }
            }
        }
    }
    
    
}
